package net.hn.hnms.biz.blueprint.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.hn.hnms.biz.blueprint.domain.Catalog;
import net.hn.hnms.biz.blueprint.mapper.CatalogMapper;
import net.hn.hnms.biz.blueprint.request.CatalogPermissionReq;
import net.hn.hnms.biz.blueprint.request.CatalogReq;
import net.hn.hnms.biz.blueprint.service.ICatalogService;
import net.hn.hnms.biz.blueprint.vo.CatalogVO;
import net.hn.hnms.sys.common.core.constant.Constants;
import net.hn.hnms.sys.common.core.exception.HuaNengException;
import net.hn.hnms.sys.common.satoken.utils.LoginHelper;
import net.hn.hnms.sys.file.api.RemoteFileService;
import net.hn.hnms.sys.system.api.RemoteDeptService;
import net.hn.hnms.sys.system.api.RemoteUserService;
import net.hn.hnms.sys.system.api.domain.SysDept;
import net.hn.hnms.sys.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wangjingrui
 * @date 2022/9/15 10:28
 */
@Service
public class CatalogServiceImpl implements ICatalogService {

    private final static Logger log = LoggerFactory.getLogger(CatalogServiceImpl.class);

    @Autowired
    private CatalogMapper catalogMapper;

    @Autowired
    private RemoteFileService fileService;

    @Autowired
    private RemoteUserService userService;

    @Autowired
    private RemoteDeptService deptService;

    /**
    * 获取目录树状结构
    */
    @Override
    public List<CatalogVO> treeCatalog() {
        List<Catalog> catalogs = getPermissionCatalog();
        if(CollUtil.isEmpty(catalogs)) return null;
        Map<String, CatalogVO> catalogMap = new HashMap<>(catalogs.size());
        List<CatalogVO> catalogVOs = new ArrayList<>();
        for (Catalog catalog : catalogs) {
            CatalogVO vo = BeanUtil.copyProperties(catalog, CatalogVO.class);
            if(null != catalog.getOrgIds() && catalog.getOrgIds().length > 0) {
                Set<Long> orgIdSet = Arrays.stream(catalog.getOrgIds()).collect(Collectors.toSet());
                vo.setOrgIdList(orgIdSet);
                vo.setAllDeptIdList(orgIdSet);
            }
            if(null != catalog.getUserIds() && catalog.getUserIds().length > 0) {
                List<Long> userIdList = Arrays.asList(catalog.getUserIds());
                vo.setUserIdList(userIdList);
                List<LoginUser> userList = userService.getUserListByIdList(userIdList);
                if(CollUtil.isNotEmpty(userList)){
                    vo.getAllDeptIdList().addAll(userList.stream().map(LoginUser::getDeptId).collect(Collectors.toSet()));
                }
            }
            catalogVOs.add(vo);
            catalogMap.put(catalog.getCatalogId(), vo);
        }

        List<CatalogVO> firstCatalogs = new ArrayList<>();
        for (CatalogVO catalog : catalogVOs) {
            if(StrUtil.isBlank(catalog.getParentId())){
                firstCatalogs.add(catalog);
            } else {
                CatalogVO parentCatalog = catalogMap.get(catalog.getParentId());
                parentCatalog.getChildren().add(catalog);
            }
        }
        return firstCatalogs;
    }

    @Override
    public void saveCatalog(CatalogReq req) {
        if(StrUtil.isNotBlank(req.getCatalogId())){
            updateCatalog(req);
        } else {
            addCatalog(req);
        }
    }

    /**
     * 新增目录
     */
    public void addCatalog(CatalogReq req) {
        boolean root = StrUtil.isBlank(req.getParentId());
        LambdaQueryWrapper<Catalog> query = new LambdaQueryWrapper<>();
        query.eq(Catalog::getCatalogName, req.getCatalogName());
        query.eq(!root, Catalog::getParentId, req.getParentId());
        Long count = catalogMapper.selectCount(query);
        if(count != 0L) throw new HuaNengException(Constants.FAIL,"目录名称已存在");

        Catalog catalog = BeanUtil.copyProperties(req, Catalog.class);
        if(!root){
            Catalog parent = catalogMapper.selectById(req.getParentId());
            if(parent == null) throw new HuaNengException(Constants.FAIL,"父目录不存在");
            if(StrUtil.isNotBlank(parent.getAncestors())){
                catalog.setAncestors(StrUtil.join(",",parent.getAncestors(), parent.getCatalogId()));
            } else {
                catalog.setAncestors(parent.getCatalogId());
            }
        }
        catalogMapper.insert(catalog);
    }

    /**
     * 修改目录
     */
    public void updateCatalog(CatalogReq req) {
        if(StrUtil.equals(req.getParentId(), req.getCatalogId())) throw  new HuaNengException(Constants.FAIL, "上级目录不能是自己");

        Catalog catalog = catalogMapper.selectById(req.getCatalogId());
        if(catalog == null) throw new HuaNengException(Constants.FAIL, "目录不存在");

        List<Catalog> catalogs = getPermissionCatalog();
        if(CollUtil.isEmpty(catalogs) ||
                !catalogs.stream().map(Catalog::getCatalogId).collect(Collectors.toList()).contains(req.getCatalogId())) {
            log.error("没有操作目录: {}的权限", catalog.getCatalogName());
            throw new HuaNengException(Constants.FAIL, "您没有操作权限");
        }

        Catalog parent = null;
        if(StrUtil.isNotBlank(req.getParentId())){
            parent = catalogMapper.selectById(req.getParentId());
            if(parent == null) throw new HuaNengException(Constants.FAIL, "父级目录不存在");
        }

        // 移动到其他目录下, 需判断目录名称是否存在, 更新要修改目录的parent和更新子目录ancestors, 更新子目录ancestors
        if(!StrUtil.equals(catalog.getParentId(), req.getParentId())){
            LambdaQueryWrapper<Catalog> query = new LambdaQueryWrapper<>();
            query.eq(Catalog::getCatalogName, req.getCatalogName());
            query.eq( Catalog::getParentId, req.getParentId());
            Long count = catalogMapper.selectCount(query);
            if(count != 0L) throw new HuaNengException(Constants.FAIL,"目录名称已存在");

            String oldAncestors = catalog.getAncestors();
            String newAncestors = catalog.getCatalogId();
            if(parent != null) {
                newAncestors = StrUtil.isNotBlank(parent.getAncestors()) ? parent.getAncestors() + "," + parent.getCatalogId() : parent.getCatalogId();
                catalog.setParentId(parent.getCatalogId());
                catalog.setAncestors(newAncestors);
            } else {
                catalog.setParentId(null);
                catalog.setAncestors(null);
            }

            List<Catalog> childrenCatalogs = selectChildren(catalog.getCatalogId());
            if(CollUtil.isNotEmpty(childrenCatalogs)){
                for (Catalog child : childrenCatalogs) {
                    child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
                }
                catalogMapper.updateBatchById(childrenCatalogs);
            }
        }

        catalog.setCatalogName(req.getCatalogName());
        catalogMapper.updateById(catalog);
    }

    /**
     * 查询子目录
    */
    private List<Catalog> selectChildren(String catalogId) {
        QueryWrapper<Catalog> childrenQuery = new QueryWrapper<>();
        childrenQuery.apply("'" + catalogId + "' = ANY (string_to_array(ancestors, ','))");
        List<Catalog> childrenCatalogs = catalogMapper.selectList(childrenQuery);
        return childrenCatalogs;
    }

    /**
     * 分配目录权限
     */
    @Override
    public void authorizeCatalog(CatalogPermissionReq req) {
        checkAdmin();
        Catalog catalog = catalogMapper.selectById(req.getCatalogId());
        if(catalog == null) throw new HuaNengException(Constants.FAIL, "目录不存在");

        List<LoginUser> userList = userService.getUserListByIdList(req.getUserIds());
        Set<Long> userIds = userList.stream().map(LoginUser::getUserId).collect(Collectors.toSet());
        catalog.setUserIds(userIds.toArray(new Long[userIds.size()]));

        if(CollUtil.isNotEmpty(req.getOrgIds())) {
            List<SysDept> deptList = deptService.getDeptByIds(req.getOrgIds());
            Set<Long> deptIds = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toSet());
            catalog.setOrgIds(deptIds.toArray(new Long[deptIds.size()]));
        }

        catalogMapper.updateById(catalog);
    }

    /**
     * 删除目录
     */
    @Transactional
    @Override
    public void deleteCatalog(List<String> catalogIds) {
        checkAdmin();
        List<Catalog> catalogs = catalogMapper.selectBatchIds(catalogIds);
        if(CollUtil.isEmpty(catalogs)) return;

        List<String> allIds = catalogs.stream().map(Catalog::getCatalogId).collect(Collectors.toList());
        List<Long> allOssIds = new ArrayList<>();
        for (Catalog catalog : catalogs) {
            List<Catalog> children = selectChildren(catalog.getCatalogId());
            if(CollUtil.isEmpty(children)) continue;

            allIds.addAll(children.stream().map(Catalog::getCatalogId).collect(Collectors.toList()));
            for (Catalog child : children) {
                if(child.getOssIds() != null) allOssIds.addAll(Arrays.asList(child.getOssIds()));
            }
        }

        if(CollUtil.isNotEmpty(allIds)) catalogMapper.deleteBatchIds(allIds);

        if(CollUtil.isNotEmpty(allOssIds)) fileService.remove(allOssIds.toArray(new Long[allOssIds.size()]));
    }

    /**
     * 目录列表
     */
    @Override
    public List<CatalogVO> listCatalog() {
        List<Catalog> catalogs = getPermissionCatalog();
        //TODO 返回提示设置对应目录权限
        if(CollUtil.isEmpty(catalogs)) return null;

        List<CatalogVO> result = new ArrayList<>();
        catalogs.forEach(item -> result.add(BeanUtil.copyProperties(item, CatalogVO.class)));
        return result;
    }


    private void checkAdmin(){
        if(LoginHelper.isAdmin()) return;
        throw new HuaNengException(Constants.FAIL,"您没有操作权限");
    }

    private List<Catalog> getPermissionCatalog(){
        List<Catalog> catalogs = catalogMapper.selectList();
        if (CollUtil.isEmpty(catalogs)  || catalogs.get(0) == null) return null;

        // 管理员拥有全部权限
        if (LoginHelper.isAdmin()) return catalogs;
        //暂时不控制权限
//        if (true) return catalogs;

        LoginUser loginUser = LoginHelper.getLoginUser();
        Long userId = loginUser.getUserId();
        Long deptId = loginUser.getDeptId();

        List<Catalog> result = new ArrayList<>();

        SysDept sysDept = deptService.getDeptByIds(Arrays.asList(deptId)).get(0);
        List<String> ancestors = Arrays.asList(sysDept.getAncestors().split(","));
        //如果该用户是根组织机构下的  则拥有全部指定了权限的目录
//        if (CollUtil.isEmpty(ancestors)) {
//            catalogs.forEach(item -> {
//                if ((item.getOssIds() != null || item.getOssIds().length != 0) &&
//                     (item.getUserIds() != null || item.getUserIds().length != 0)){
//                    result.add(item);
//                }
//            });
//            return result;
//        }

        for (Catalog catalog : catalogs) {
            List<Long> userIdList = Arrays.asList(catalog.getUserIds());
            //目录中指定了该用户则有权限
            if(CollUtil.contains(userIdList,userId)) {
                result.add(catalog);
                continue;
            }
//            List<Long> orgIdList = Arrays.asList(catalog.getOrgIds());
//            //判断其组织机构是否有权限
//            if(CollUtil.contains(orgIdList,deptId)) {
//                result.add(catalog);
//                continue;
//            }
//            //判断上级机构是否有权限
//            orgIdList.retainAll(ancestors);
//            if(CollUtil.isNotEmpty(orgIdList)){
//                result.add(catalog);
//            }
        }
        return result;
    }
}
